from flask import request
import json

from redash import models, settings
from redash.handlers.base import BaseResource
from redash.serializers import serialize_widget
from redash.permissions import (
    require_access,
    require_object_modify_permission,
    require_permission,
    view_only,
)
from redash.utils import json_loads, json_dumps


class WidgetListResource(BaseResource):
    @require_permission("edit_dashboard")
    def get(self):
        widgets = models.Widget.get_template_all(self.current_org)
        return [serialize_widget(widget, False, False) for widget in widgets]

    @require_permission("edit_dashboard")
    def post(self):
        """
        Add a widget to a dashboard.

        :<json number dashboard_id: The ID for the dashboard being added to
        :<json visualization_id: The ID of the visualization to put in this widget
        :<json object options: Widget options
        :<json string text: Text box contents
        :<json number width: Width for widget display

        :>json object widget: The created widget
        """
        widget_properties = request.get_json(force=True)
        dashboard = models.Dashboard.get_by_id_and_org(
            widget_properties.get("dashboard_id"), self.current_org
        )
        require_object_modify_permission(dashboard, self.current_user)

        widget_properties["options"] = json_dumps(widget_properties["options"])
        widget_properties.pop("id", None)

        visualization_id = widget_properties.pop("visualization_id")
        if visualization_id:
            visualization = models.Visualization.get_by_id_and_org(
                visualization_id, self.current_org
            )
            require_access(visualization.query_rel, self.current_user, view_only)
        else:
            visualization = None

        widget_properties["visualization"] = visualization

        widget = models.Widget(**widget_properties)
        models.db.session.add(widget)
        models.db.session.commit()

        models.db.session.commit()
        return serialize_widget(widget)


class WidgetResource(BaseResource):
    @require_permission("edit_dashboard")
    def post(self, widget_id):
        """
        Updates a widget in a dashboard.
        This method currently handles Text Box widgets only.

        :param number widget_id: The ID of the widget to modify

        :<json string text: The new contents of the text box
        """
        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
        require_object_modify_permission(widget.dashboard, self.current_user)
        widget_properties = request.get_json(force=True)
        widget.text = widget_properties["text"]
        if "visualization_id" in widget_properties:
            widget.visualization_id = widget_properties["visualization_id"]
        widget.options = json_dumps(widget_properties["options"])
        models.db.session.commit()
        return serialize_widget(widget)

    @require_permission("edit_dashboard")
    def delete(self, widget_id):
        """
        Remove a widget from a dashboard.

        :param number widget_id: ID of widget to remove
        """
        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
        require_object_modify_permission(widget.dashboard, self.current_user)
        self.record_event(
            {"action": "delete", "object_id": widget_id, "object_type": "widget"}
        )
        models.db.session.delete(widget)
        models.db.session.commit()


class WidgetTemplateResource(BaseResource):
    @require_permission("edit_dashboard")
    def get(self, widget_id, dashboard_id, row, col):
        widget = models.Widget.get_by_id(widget_id)
        dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org)
        if widget.visualization is not None:
            visualization = models.Visualization.get_by_id(widget.visualization.id)
            query = models.Query.by_id(visualization.query_id)
            forked_query = query.fork(self.current_user, query.name + "：" + widget.template_name, query.data_source, False, visualization.id)

        options = json.loads(widget.options)
        options["position"]["row"] = row;
        options["position"]["col"] = col;

        fork_widget = models.Widget(
            dashboard = dashboard,
            visualization = forked_query.visualizations[1] if widget.visualization is not None else None,
            width = widget.width,
            text = widget.text,
            options = json.dumps(options),
            template_type = 0,
            template_name = widget.template_name,
            template_logo = widget.template_logo,
        )
        models.db.session.add(fork_widget)
        models.db.session.commit()

        return serialize_widget(fork_widget)

    @require_permission("edit_dashboard")
    def post(self, widget_id, visualization_id, key):
        template_properties = request.get_json(force=True)

        visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)

        template_parameters = visualization.template_parameters
        template_parameters[key].update(template_properties)
        
        if visualization.template_options is not None and bool(visualization.template_options):
            template_options = json_dumps(visualization.template_options)
            for k in template_parameters:
                param = template_parameters[k]
                if param["type"] == "image":
                    widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
                    logoFolder = widget.template_logo.replace(".png","")
                    value = "/static/images/templates/" + logoFolder + "/" + str(param["value"]) + ".png"
                    template_options = template_options.replace("<<" + k + ">>", value)
                elif param["type"] == "display":
                    style = ""
                    if "fontcolor" in param:
                        style = style + "color: " + param["fontcolor"] + "; "
                    if "fontsize" in param:
                        style = style + "font-size: " + param["fontsize"] + "px"
                    template_options = template_options.replace("<<" + k + "_style>>", style)
                elif param["type"] == "enum":
                    value = str(param["value"])
                    template_options = template_options.replace("<<" + k + ">>", value)

                if param["type"] == "display" or param["type"] == "data":
                    datasource_id = int(param["datasource"]) if "datasource" in param else 0
                    if datasource_id == 0:
                        value = param["data"]
                    elif param["type"] == "display":
                        value = "{{\\\"query\\\":0, \\\"colName\\\":\\\"0\\\", \\\"rowNumber\\\":0}}"
                    else:
                        value = "{{\\\"querys\\\":0, \\\"colName\\\":\\\"0\\\", \\\"rowNumber\\\":0}}"
                    template_options = template_options.replace("<<" + k + ">>", value)

            #模板根据属性值替换
            kwargs = {
                "options": template_options, 
            }
            self.update_model(visualization, kwargs)

        #更新数据源和SQL语句
        if "data" in template_properties or "datasource" in template_properties:
            param = template_parameters[key]
            if "datasource" in param and int(param["datasource"])>0:
                query = models.Query.get_by_id_and_org(visualization.query_id, self.current_org)
                if "datasource" in template_properties:
                    query.data_source = models.DataSource.get_by_id_and_org(int(param["datasource"]), self.current_org)
                if "data" in template_properties:
                    query.query_text = param["data"]
                models.db.session.add(query)
    
        #更新属性现值
        if settings.SQLALCHEMY_DATABASE_URI.find("mysql") == 0:
            sql = "update visualizations set template_parameters = \'" + json_dumps(template_parameters) 
            sql = sql + "\' where id=" + str(visualization.id)
        else:
            sql = "update public.visualizations set template_parameters = \'" + json_dumps(template_parameters) 
            sql = sql + "\'::json where id=" + str(visualization.id)
        models.db.session.execute(sql)
        models.db.session.commit()  
        
        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
        return serialize_widget(widget)